#ifndef AWSPARSER
#define AWSPARSER

#include "VMPFocus.hpp"
#include "operations.hpp"
#include "regexpnode.hpp"

#include <ctime>

using namespace std;

typedef regexp<char> cRegExp;

class AWSParser{
	
};

ptrParsedElement MkTree(ptrText code, const ptrIdentity identity){
	ptrParsedElement 
		Result=new cParsedElement(identity->Operation),
		tmp;
	for(int i=0; i<identity->SubIdentities->length(); ++i){
		if (tmp=MkTree(code,(*(identity->SubIdentities))[i]))		//if it doesn't return a pPE, do nothing.
			Result->push(tmp);
	};
	if (identity->Operation->onMakingTree){
	  //----For the sake of pointer rubbish.
		//old:tmp=identity->Operation->onMakingTree(identity, Result);	//Check if it returns another cPE.
		tmp=identity->Operation->onMakingTree(code, identity, Result);	//Check if it returns another cPE.
		if (tmp!=Result) delete Result;
		return tmp;
	  //----
	}else
		return Result;
}
		
	
bool PIExisted(ListIdentity* x, ptrOperation op, cRange range){
	for(int i=0; i<x->length(); ++i)
		if ((*x)[i]->Range==range&&(*x)[i]->Operation==op)
			return true;
	return false;
}

class CodeUnParsedError{};
ptrParsedElement Lining(cText& code){
    ListIdentity		identities;
    sRegExpReturn       handling;
	cRegExp				RegExp(&code);
	
//	srand(time(NULL));
	int k=0;
	//Create operations list.
	StrHashmap<ptrOperation>::iterator Ti;
	lsOperations.clear();
	for (Ti=Operations.begin(); Ti!=Operations.end(); ++Ti)
		lsOperations.push(Ti->second);

	while(1){
		bool roundOK=false;
		for(int i=0; i<lsOperations.length(); ++i){
			//cout<<"finding:"<<lsOperations[i]->Name<<endl;
			//PreLining: replace with "higher", "expression", etc.
			RegExp.init(&(lsOperations[i]->Formula));

			if (lsOperations[i]->onPreLining)
				lsOperations[i]->onPreLining(&identities);

			for(;;){
				//Regular Expression Matching:
				handling=RegExp.findNext(&identities);
				if (handling.found){
					//Already Exist with same operation:
					if (PIExisted(&identities,lsOperations[i],handling.range)) continue;
					//Lining:
					roundOK=true;
					ptrIdentity current= 
						ReturnIdentity(
							handling.range,            //Range
							NULL,//lsOperations[i]->Name,	   //Name
							lsOperations[i],           //Operation Pointer
							handling.Matched           //SubIdentities.
						);
					if (lsOperations[i]->onFoundIdentity)
						lsOperations[i]->onFoundIdentity(current);
					identities.push(current);
					
					//Is Lining to end?
					if (handling.range==cRange(0,code.length()-1)){
						cout<<"****************************************************";
						return MkTree(&code,current);
					};

					cout<<++k<<'~'<<lsOperations[i]->Name<<":OK! -("<<handling.range.begin<<','<<handling.range.end<<"):"<<endl<<code.substr(handling.range.begin,handling.range.end-handling.range.begin+1)<<endl;
					
					//Destory handling.matched:
					//delete handling.Matched;
				}
				else 
					break; //for(;;)
			};
			
			if (lsOperations[i]->onPostLining)
				lsOperations[i]->onPostLining(&identities);
		};
		cout<<"------------- Round! -----------------\n";
		if (roundOK==false)
			throw CodeUnParsedError(); //Lining Not Complete.
	};
}

#endif